package com.aces2win.server.backtestengine;

import java.util.ArrayList;
import java.util.logging.Logger;

import com.aces2win.server.entities.Quote;
import com.aces2win.server.entities.Trade;
import com.aces2win.server.entities.Wallet;

public class BackTestEngine {
	private static final Logger log =
		      Logger.getLogger(BackTestEngine.class.getName());
	
	// wallet used to make simulation
	private Wallet wallet;
	// quotes tested
	private ArrayList<Quote> quotes;
	
	public BackTestEngine(Wallet w,ArrayList<Quote> quotes){
		this.wallet = w;
		this.quotes = quotes;
	}
	
	
	// main method to launch backtest engine
	public void	perform(Criterias c) throws AmbiguousSituationException{
		ArrayList<Quote> tempQuotes = new ArrayList<Quote>();
		ArrayList<Trade> trades = new ArrayList<Trade>();
		Trade currentTrade = new Trade();
		
		// Long for next Quote ?
		boolean isLong = false;
		// Short for next Quote ?
		boolean isShort = false;
		// Do we need to close Position ?
		boolean isClosingSignal = false;
		// currently in position ?
		boolean isCurrentlyInPosition = false;
		
		for(Quote q : quotes){
			
			/****************CLOSE CONDITIONS BEGIN******************/
			if(isClosingSignal&&isCurrentlyInPosition){
				log.info("We try to close current Trade ");
				currentTrade.closeTrade(q.getQuoteDate(), currentTrade.getVolume()*q.getOpen());
				isClosingSignal = false;
				isCurrentlyInPosition = false;
			}
			/****************CLOSE CONDITIONS END********************/
			
			
			/****************STOP LOSS CONDITIONS BEGIN******************/
			if(currentTrade.isLong()){
				double low = q.getLow();
				double stopLossPrice = c.stopLossConditions(tempQuotes, currentTrade);
				
				if(stopLossPrice!=-1&&stopLossPrice>low){
					log.info("Stop Loss activated");
					currentTrade.closeTrade(q.getQuoteDate(),currentTrade.getVolume()*stopLossPrice);
					currentTrade.setMaxDrawDawn(low);
					wallet.addTrade(currentTrade);
					isCurrentlyInPosition = false;
				}
			}else{
				double high = q.getHigh();
				double stopLossPrice = c.stopLossConditions(tempQuotes, currentTrade);
				
				if(stopLossPrice!=-1&&stopLossPrice<high){
					log.info("Stop Loss activated");
					currentTrade.closeTrade(q.getQuoteDate(),currentTrade.getVolume()*stopLossPrice);
					currentTrade.setMaxDrawDawn(high);
					wallet.addTrade(currentTrade);
					isCurrentlyInPosition = false;
				}
			}
			/****************STOP LOSS CONDITIONS END********************/
			
			
			
			
			/****************STOP PROFIT CONDITIONS BEGIN******************/
			if(currentTrade.isLong()){
				double high = q.getHigh();
				double stopProfitPrice = c.stopProfitConditions(tempQuotes, currentTrade);
				
				if(stopProfitPrice!=-1&&stopProfitPrice<high){
					log.info("Stop Profit activated");
					currentTrade.closeTrade(q.getQuoteDate(),currentTrade.getVolume()*stopProfitPrice);
					currentTrade.setMaxDrawDawn(q.getLow());
					wallet.addTrade(currentTrade);
					isCurrentlyInPosition = false;
				}
			}else{
				double low = q.getLow();
				double stopProfitPrice = c.stopProfitConditions(tempQuotes, currentTrade);
				
				if(stopProfitPrice!=-1&&stopProfitPrice>low){
					log.info("Stop Profit activated");
					currentTrade.closeTrade(q.getQuoteDate(),currentTrade.getVolume()*stopProfitPrice);
					currentTrade.setMaxDrawDawn(q.getHigh());
					wallet.addTrade(currentTrade);
					isCurrentlyInPosition = false;
				}
			}
			/****************STOP PROFIT CONDITIONS END********************/
			
			
			/****************EVALUATE MAXDRAWDAWN BEGIN******************/
			if(isCurrentlyInPosition){
				if(currentTrade.isLong()){
					currentTrade.setMaxDrawDawn(q.getLow());
				}else{
					currentTrade.setMaxDrawDawn(q.getHigh());
				}
			}
			/****************EVALUATE MAXDRAWDAWN END******************/
			
			
			/****************TAKING POSITION BEGIN***********************/
			if(isCurrentlyInPosition!=true){
				if(isLong||isShort){
					
					long volume = c.sizingConditions(tempQuotes, wallet);
					currentTrade = new Trade();
					currentTrade.openTrade(q.getQuoteDate(), volume*q.getOpen(), isLong);
					log.info("Position taken "+currentTrade.toString());
					// I update my new wallet balance
					wallet.addTrade(currentTrade);
					
					// I reinit my positions
					isLong = false;
					isShort = false;
				}
			}
			/****************TAKING POSITION END*************************/
			
			
			// I put my new quote to evaluate the new situation
			tempQuotes.add(q);
			// I'm looking for if I can get Long or Short
			isLong 	= c.longConditions(tempQuotes);
			isShort = c.shortConditions(tempQuotes);
			isClosingSignal = c.closePosition(tempQuotes, isLong);
			
			// I cannot be Long and Short at the same time
			// weird situation it seems like I have stupid criterias
			if(isLong&&isShort)
				throw new AmbiguousSituationException();
			wallet.updateWalletHistory(q.getQuoteDate());
		}
	}
	
}
